package com.onpositive.wiki3.db;

import java.io.File;
import java.io.IOException;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Set;

import com.carrotsearch.hppc.IntOpenHashSet;
import com.onpositive.wiki3.db.catmodel.CompactCats;
import com.onpositive.wiki3.db.catmodel.CompactCats.DS;
import com.onpositive.wiki3.db.impl.CountingVocabalary;

public class SimpleReconciler implements IReconciler {

	protected IWikiDB db;
	protected CompactCats store;

	public SimpleReconciler(IWikiDB db) throws IOException {
		this.db = db;
		long l0 = System.currentTimeMillis();
		File f = new File(db.getPath() + "/relations/is_a.rel");
		store = new CompactCats(f, false, db);
		long l1 = System.currentTimeMillis();
		System.out.println(l1 - l0);
	}

	public Set<DS> getReconciledTypesS(String object) {
		int[] fuzzyMatches = getIds(object);
		HashSet<DS> st = new HashSet<DS>();
		for (int q : fuzzyMatches) {
			if (q == -1) {
				System.err.println("Unknown:" + object);
			}
			int redirect = db.getRedirectAccess().getRedirect(q);
			if (redirect != -1) {
				// System.out.println(db.getTitleMapper().getTitle(redirect));
				DS[] allParents = store.getAllParents(redirect, 0);
				for (DS m : allParents) {
					// System.out.println(db.getTitleMapper().getTitle(m));
					st.add(m);
				}
				// continue;
			}
			DS[] allParents = store.getAllParents(q, 0);
			for (DS m : allParents) {
				st.add(m);
			}

		}
		return st;
	}

	protected int[] getIds(String object) {
		int[] allFuzzyMatches = db.getTitleMapper().getAllFuzzyMatches(object);
		IntOpenHashSet mm = new IntOpenHashSet();
		for (int q : allFuzzyMatches) {
			int redirect = db.getRedirectAccess().getRedirect(q);
			if (redirect != -1) {
				int[] allFuzzyMatches1 = db.getTitleMapper()
						.getAllFuzzyMatches(
								db.getTitleMapper().getTitle(redirect));
				for (int z : allFuzzyMatches1) {
					// System.out.println(db.getTitleMapper().getTitle(z));
					mm.add(z);
				}
			}
			mm.add(q);
		}
		return mm.toArray();
	}

	public SimpleValueModel getReconciledTypeSoft(CountingVocabalary object) {
		SimpleValueModel simpleValueModel = new SimpleValueModel(db, store,object);
		return simpleValueModel;
	}

	protected String simpleTrim(String s) {
		return s.toLowerCase().replace((CharSequence) " ", "")
				.replace((CharSequence) "_", "");
	}

	@Override
	public Set<String> getReconciledType(String... object) {
		Set<DS> m = null;
		HashMap<DS, Integer> vm = new HashMap<CompactCats.DS, Integer>();

		for (String q : object) {
			if (m == null) {
				m = getReconciledTypesS(q);
				// System.out.println(q + ":" + m);
				for (DS z : m) {
					vm.put(z, z.distance);
				}
			} else {
				Set<DS> reconciledTypes = getReconciledTypesS(q);
				// System.out.println(q + ":" + reconciledTypes);
				for (DS r : reconciledTypes) {
					Integer integer = vm.get(r);
					if (integer != null) {
						vm.put(r, Math.max(r.distance, integer));
					}
				}
				m.retainAll(reconciledTypes);
			}
		}
		int count = Integer.MAX_VALUE;
		DS sss = null;
		HashSet<String> mq = new HashSet<String>();
		HashMap<DS, Integer> nmm = new HashMap<CompactCats.DS, Integer>();
		for (DS d : m) {
			String title = db.getTitleMapper().getTitle(d.value);

			if (title.contains("redirects")) {
				continue;
			}
			if (title.contains("articles")) {
				continue;
			}

			int distance = vm.get(d);
			if (title.contains("disputes")) {
				distance += 3;
			}
			if (title.contains("_by_")) {
				distance += 3;
			}
			if (title.contains("disambiguation")) {
				distance += 100;
			}
			if (title.contains("categories")) {
				distance += 10;
			}
			if (title.contains("use_dmy")) {
				distance += 10;
			}
			if (Character.isDigit(title.charAt(0))) {
				distance += 5;
			}
			if (distance > 1) {
				distance += title.split("_").length;
			}
			long allChildren1 = store.getInnaccurateSize(d.value);
			if (allChildren1 < 5000) {
				distance -= 1;
			}
			nmm.put(d, distance);
			System.out.println(title + ":" + distance + ":" + allChildren1);

			if (distance <= count) {
				if (sss != null && distance == count) {
					count = distance;
					// mc=allChildren1;
					long allChildren = store.getInnaccurateSize(sss.value);
					// DS[] allChildren1 = store.getAllChildren(d.value, 0);
					if (allChildren1 < allChildren) {
						sss = d;
					} else {
						continue;
					}

				}
				count = distance;
				sss = d;
			}
			if (distance < 2 && allChildren1 < 10000 && mq.size() <= 3) {
				mq.add(title);
			}
		}
		for (DS q : nmm.keySet()) {
			if (nmm.get(q) <= count) {
				long allChildren1 = store.getInnaccurateSize(q.value);
				if (allChildren1 < 10000) {
					mq.add(db.getTitleMapper().getTitle(q.value));
				}
			}
		}
		if (sss != null) {

			Set<String> singleton = Collections.singleton(db.getTitleMapper()
					.getTitle(sss.value));
			mq.addAll(singleton);
			return mq;
		}
		return Collections.emptySet();
	}

	@Override
	public Set<String> getReconciledTypes(String object) {
		// TODO Auto-generated method stub
		return null;
	}

	public Collection<String> getChildren(int id2) {
		int[] children = store.getChildren(id2);
		HashSet<String>ts=new HashSet<String>();
		for (int q:children){
			String title = db.getTitleMapper().getTitle(q);
			ts.add(title);
		}
		return ts;		
	}

	public Collection<String> getParents(int id2) {
		try{
		int[] children = store.getParents(id2);
		HashSet<String>ts=new HashSet<String>();
		for (int q:children){
			String title = db.getTitleMapper().getTitle(q);
			ts.add(title);
		}
		return ts;
		}
		catch (Exception e){
			return null;
		}
	}

}
